/*
 * Flashlib - QB9 common Flash library
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 
package com.qb9.flashlib.easing 
{
	import com.qb9.flashlib.lang.assert;
	import com.qb9.flashlib.utils.ObjectUtil;

	/**
	 * Single-class access to all easing functions.
	 *
	 * <p>This class groups all easing functions and allows to access
	 * them using string identifiers, via <code>getFunction()</code></p>
	 *
	 * @see getFunction
	 * @see "examples/easing"
	 */
	public class Easing
	{
		private static var functions:Object = {}
		
		private static function _init():void
		{
			registerFunction("linear", Linear.ease);
			registerFunction("easein", Quad.easeIn);
			registerFunction("easeout", Quad.easeOut);
			registerFunction("easeinout", Quad.easeInOut);
			registerEasingGroup("Back", Back);
			registerEasingGroup("Bounce", Bounce);
			registerEasingGroup("Circ", Circ);
			registerEasingGroup("Cubic", Cubic);
			registerEasingGroup("Elastic", Elastic);
			registerEasingGroup("Expo", Expo);
			registerEasingGroup("Quad", Quad);
			registerEasingGroup("Quart", Quart);
			registerEasingGroup("Quint", Quint);
			registerEasingGroup("Sine", Sine);
		}
		
		_init();

		/**
		 * Register a group of three easing functions: easeIn, easeOut, easeInOut.
		 *
		 * <p>The functions must be static and all must belong to the same class.</p>
		 */
		public static function registerEasingGroup(id:String, klass:Class):void
		{
			registerFunction(id + "easein", klass.easeIn);
			registerFunction(id + "easeout", klass.easeOut);
			registerFunction(id + "easeinout", klass.easeInOut);
		}

		/**
		 * Return the easing function that corresponds to the given identifier.
		 *
		 * <p>The following special identifiers are accepted: "linear", "easeIn", "easeOut", "easeInOut",
		 * which map to the Linear and Quad easing functions.</p>
		 *
		 * <p>The rest of the easing functions have <code>class + function</code> identifiers.  For example,
		 * the <code>Cubic.easeIn</code> function can be accessed with the "cubicEaseIn" id.  See the example
		 * at <code>examples/easing</code> to see the full list of supported functions.
		 * </p>
		 *
		 * <p>Identifiers are case insensitive, and any periods (.) are ignored: "expoEaseOut", "ExpoEaseOut", "expoeaseout", "Expo.easeOut" all map
		 * to the same function: <code>Expo.easeOut</code>.</p>
		 */
		public static function getFunction(id:String = "linear"):Function
		{
			if (id == "" || id == null) id = "linear";
			id = normalizedId(id);
			assert(functions[id] != undefined, "Undefined transition function: " + id);
			return functions[id];
		}

		/**
		 * Register a new easing function.
		 *
		 * <p>After this call, the function can be accessed with getFunction().</p>
		 */
		public static function registerFunction(id:String, f:Function):void
		{
			id = normalizedId(id);
			if (functions[id])
				throw new Error("Easing function with identifier: '" + id + "' already exists.");
			functions[id] = f;
		}
		
		/** Return the normalized version of a function identifier (lower case & ignore periods). */
		private static function normalizedId(id:String):String
		{
			return id.toLowerCase().replace(".", "");
		}

		/** Return a id -> function map. */
		public static function getAllFunctions():Object
		{
			return ObjectUtil.copy(functions);
		}
	}
}

